﻿using System;
using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
using UIFrameWork;
using UnityEngine;
//提供在resource上加载资源的管理脚本
namespace UIFrameWork
{   
     public class AssetInfo
     {
         private UnityEngine.Object _Object = null;
         public Type AssetType { get; set; }
         public string Path { get; set; }
         private int refcount = 0;

         public void AddRefCount()
         {
             refcount++;
         }

         public bool SubRefCount()
         {
             refcount--;
             if (refcount == 0)
             {
                 GameObject.Destroy(_Object);
                 return true;
             }
             return false;
         }

         public bool IsLoad
         {
             get { return null != _Object; }
         }

         public UnityEngine.Object AssetObject
         {
             get
             {
                 if (_Object == null)
                 {
                     //加载
                     ResourcesLoad();
                 }
                 return _Object;
             }
         }

         public IEnumerator GetCoroutineObject(Action<UnityEngine.Object> callback)
         {
             while (true)
             {
                 yield return null;
                 if (null == _Object)
                 {
                     ResourcesLoad();
                 }
                 yield return null;
                 if (callback != null)
                 {
                     callback(_Object);
                 }
                 yield break;
             }             
         }
         public IEnumerator GetAsyncObject(Action<UnityEngine.Object> callback)
         {
             return GetAsyncObject(callback, null);
         }

         public IEnumerator GetAsyncObject(Action<UnityEngine.Object> callback, Action<float> process)
         {
             if (_Object != null)
             {
                 if (callback != null)
                 {
                     callback(_Object);
                 }
                 yield break;
             }
             ResourceRequest resourceRequest = Resources.LoadAsync(Path);
             while (resourceRequest.progress<0.9)
             {
                 if (process != null)
                 {
                     process(resourceRequest.progress);
                 }
                 yield return null;
             }
             while (resourceRequest.isDone==false) 
             {
                 if (process != null)
                 {
                     process(resourceRequest.progress);
                 }
                 yield return null;
             }
             _Object = resourceRequest.asset;
             if (callback != null)
             {
                 callback(_Object);
             }
             yield return resourceRequest;
         }

         public void ResourcesLoad()
         {
             _Object = Resources.Load<GameObject>(Path);
             if (_Object == null)
             {
                 Debug.LogError("加载失败 路径为"+Path);
             }

         }
     }
    
    public class ResourcesManager:Singleton<ResourcesManager>
    {
        private Dictionary<string, AssetInfo> AssetInfos = null;
        public override void Init()
        {
            AssetInfos = new Dictionary<string, AssetInfo>();
        }

        public AssetInfo GetAssetInfo(string name)
        {
            return GetAssetInfo(name, null);
        }
        public AssetInfo GetAssetInfo(string name,Action<UnityEngine.Object> callback)
        {
            if (string.IsNullOrEmpty(name))
            {
                Debug.LogError("name不能为空");
                if (callback != null)
                {
                    callback(null);
                }
                return null;
            }
            AssetInfo assetInfo = null;
            AssetInfos.TryGetValue(name, out assetInfo);
            if (assetInfo == null)
            {
                assetInfo = new AssetInfo();
                assetInfo.Path = name;
                AssetInfos.Add(name,assetInfo);
                
            }
            else
            {
                assetInfo.AddRefCount();
            }
            return assetInfo;

        }
        #region Load Res & Instance Obj

        public UnityEngine.Object Load(string path)
        {
            AssetInfo assetInfo = GetAssetInfo(path);
            if (null != assetInfo)
            {
                return assetInfo.AssetObject;
            }
            return null;
        }

        private UnityEngine.Object Instantiate(UnityEngine.Object obj, Action<UnityEngine.Object> callback)
        {
            UnityEngine.Object retobj = null;
            if (obj == null)
            {
                Debug.LogError("实例化出错");
                return null;
            }
            retobj = GameObject.Instantiate(obj);
            if (retobj != null)
            {
                if (callback != null)
                {
                    callback(retobj);
                }
            }
            else
            {
                Debug.LogError("实例化出错");
            }
            return retobj;

        }
        public void LoadCoroutine(string path,Action<UnityEngine.Object> callback)
        {
            AssetInfo assetInfo = GetAssetInfo(path);
            CoroutineExecutor.Create(assetInfo.GetCoroutineObject(callback),null);
        }

        public void LoadAsync(string path, Action<UnityEngine.Object> callback)
        {
              LoadAsync(path,callback,null);
        }

        public void LoadAsync(string path, Action<UnityEngine.Object> callback, Action<float> process)
        {
            AssetInfo assetInfo = GetAssetInfo(path);
            CoroutineExecutor.Create(assetInfo.GetAsyncObject(callback,process),null);
        }
        public void LoadAsyncInstance(string path,Action<UnityEngine.Object> callback)
        {
            LoadAsync(path,(obj)=> { Instantiate(obj, callback); });
        }
        public void LoadCoroutineInstance(string path,Action<UnityEngine.Object> callback)//实例化完成后的回调参数是实例化出来的gameobject
        {
            LoadCoroutine(path,(obj)=> { Instantiate(obj, callback); });
        }
        public UnityEngine.Object LoadInstance(string path)
        {
            UnityEngine.Object obj = Load(path);
            return GameObject.Instantiate(obj);
        }
        
        #endregion
    }
}

